package com.china.produce.config.interceptor;

import cn.hutool.core.util.StrUtil;
import com.china.produce.pojo.CurrentUserInfo;
import com.china.produce.system.util.LoginUtils;
import com.china.produce.system.util.WebCommonUtil;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;

/**
 * @ClassName
 * @Author niujie
 * @Version
 * @Description
 * @CreateTime 2022/10/23
 */
@Slf4j
@Component
public class ExternalAccessInterceptor implements HandlerInterceptor{

    private static final Logger LOG = LoggerFactory.getLogger(ExternalAccessInterceptor.class);

    private static final String TOKEN_KEY = "token";

    @Value("${spring.redis.key.prefix}")
    private String redisKeyPrefix;

    @Autowired
    @Qualifier("redisTemplate2")
    private RedisTemplate redisTemplate;

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        LOG.info("url : {}", request.getRequestURL());
        LoginUtils.clear();
        LoginUtils.setSession(request.getSession());

        if (!(handler instanceof HandlerMethod)) {
            // 访问URL不是后端接口(如图片网页资源)，无需权限验证
            return true;
        }
        // 无需登录的注解
        boolean exist = LoginUtils.hasLoginNeedless(handler);
        if (exist) {
            return true;
        }
        String token = request.getHeader(TOKEN_KEY);
        LOG.info("request token: {}", token);
        if (StrUtil.isBlank(token)) {
            LOG.warn("token为空");
            returnAjaxNotLoginResponse(request,response);
            return false;
        }
        // 查询缓存数据，初始化用户信息
        String redisKey = String.format("%s:external:token:%s", redisKeyPrefix, token);
        if (Boolean.FALSE.equals(redisTemplate.hasKey(redisKey))) {
            LOG.info("invalide token: {}", token);
            LOG.warn("token redis key 不存在:{}", redisKey);
            returnAjaxNotLoginResponse(request,response);
            return false;
        }

        HashOperations<String, String, Object> hash = redisTemplate.opsForHash();
        String sessionId = (String) hash.get(redisKey, "sessionId");
        Long userId = Long.parseLong(hash.get(redisKey, "userId").toString());

        if (Objects.isNull(sessionId)) {
            LOG.warn("当前操作用户sessionId为空:{}", redisKey);
            returnAjaxNotLoginResponse(request,response);
            return false;
        }

        if (Objects.isNull(userId)) {
            LOG.warn("当前操作用户userId为空:{}", redisKey);
            returnAjaxNotLoginResponse(request,response);
            return false;
        }
        initRpcCurrentUser(sessionId, userId);

        return true;
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
                         @Nullable Exception ex) throws Exception {
        LoginUtils.clear();
    }

    private void initRpcCurrentUser(String sessionId, Long userId) {
        String key = getUserInfoKey(redisKeyPrefix, sessionId, userId);
        Object cache = redisTemplate.opsForValue().get(key);
        if (cache != null) {
            if (cache instanceof CurrentUserInfo) {
                setCurrentUser((CurrentUserInfo)cache);
            } else {
                LOG.error("The user is not front system.");
            }
        }
    }

    private static String getUserInfoKey(String redisKeyPrefix, String sessionId, Long userId) {
        return redisKeyPrefix + sessionId + String.format("SCRM_LOGIN_KEY_%s", userId);
    }

    private void setCurrentUser(CurrentUserInfo user) {
        LoginUtils.setCurrentUser(user);
    }

    private void returnAjaxNotLoginResponse(HttpServletRequest request, HttpServletResponse response) {
       // response.setStatus(HttpStatus.SC_UNAUTHORIZED);
        WebCommonUtil.returnMessage(response, "用户未登录");
    }
}
